home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / em-xmkit.zip / MEMLIB.C < prev    next >
C/C++ Source or Header  |  1989-12-01  |  89KB  |  1,760 lines

  1. /**********************************************************************/
  2. /*                                                                    */
  3. /*     Module:    MEMLIB.C                                            */
  4. /*                                                                    */
  5. /*     This module contains the C MEMORY MANAGER - a group of C       */
  6. /*     callable routines that manage expanded memory.  These          */
  7. /*     routines alleviate many of the housekeeping chores necessary   */
  8. /*     when dealing with expanded memory and make allocating and      */
  9. /*     freeing expanded memory look as much like allocating and       */
  10. /*     freeing conventional memory as possible.                       */
  11. /*                                                                    */
  12. /*     The routines called by an application are:                     */
  13. /*                                                                    */
  14. /*     ememavl         Approximate amount of free expanded memory     */
  15. /*     ememmax         Size of the largest contiguous free block      */
  16. /*     emsize          Size of a specified block                      */
  17. /*     efmalloc        Allocate a block of memory                     */
  18. /*     effree          Free a previously allocated block              */
  19. /*     seteptrs        Access n different blocks                      */
  20. /*     set1eptr        Access 1 block                                 */
  21. /*     set2eptrs       Access 2 blocks                                */
  22. /*     set3eptrs       Access 3 blocks                                */
  23. /*     push_context    Push the current mapping context               */
  24. /*     pop_context     Pop a mapping context                          */
  25. /*     effreeall       Frees ALL blocks                               */
  26. /*                                                                    */
  27. /**********************************************************************/
  28.  
  29. #include "memintrl.c"
  30.  
  31. /*$PAGE*/
  32. /**********************************************************************/
  33. /*                                                                    */
  34. /*     Name:    unsigned int ememavl (*size)                          */
  35. /*              unsigned long *size;                                  */
  36. /*                                                                    */
  37. /*     Description:                                                   */
  38. /*        Computes the size of expanded memory available in bytes but */
  39. /*     due to memory fragmentation, the largest useable block may be  */
  40. /*     smaller than the amount returned by this function.  See        */
  41. /*     ememmax.                                                       */
  42. /*                                                                    */
  43. /*     Parameters:                                                    */
  44. /*        output  size       The size computed.                       */
  45. /*                                                                    */
  46. /*     Results returned:                                              */
  47. /*        PASSED     The size is valid                                */
  48. /*        error      Non-zero value, see "ERRORS.H" or EMS table A-2  */
  49. /*                                                                    */
  50. /*     Calling sequence:                                              */
  51. /*     #include "memlib.h"                                            */
  52. /*     #include "errors.h"                                            */
  53. /*         ...                                                        */
  54. /*     unsigned long size;                                            */
  55. /*     unsigned int  status;                                          */
  56. /*         ...                                                        */
  57. /*     status = ememavl (&size);                                      */
  58. /*     if (status == PASSED)                                          */
  59. /*         printf("Expanded memory available = %lu \n", size);        */
  60. /*     else                                                           */
  61. /*         { error condition }                                        */
  62. /*                                                                    */
  63. /*     Calls: prepare_dir_mapping()                                   */
  64. /*            get_unalloc_page_count()                                */
  65. /*            restore_memlib_context()                                */
  66. /*            map_dir_page()                                          */
  67. /*                                                                    */
  68. /*     Called by:  Application                                        */
  69. /*                                                                    */
  70. /*     Globals referenced/modified: directory                         */
  71. /*                                  dir_page_count                    */
  72. /*                                                                    */
  73. /**********************************************************************/
  74.  
  75. unsigned int ememavl (size)
  76. unsigned long *size;
  77. {
  78.    unsigned int status;             /* The status of EMM and MEMLIB    */
  79.    unsigned int num_unalloc_pages;  /* Number of unallocated pages     */
  80.    unsigned int index;              /* Index into a directory page     */
  81.    unsigned int dir_page;           /* The directory page to map in    */
  82.    unsigned int context_saved;      /* Whether the contexted was saved */
  83.  
  84.    *size = 0;
  85.  
  86.    /**********************************************/
  87.    /* Call prepare_dir_mapping() to save context */
  88.    /* before mapping in the directory.           */
  89.    /**********************************************/
  90.  
  91.    status = prepare_dir_mapping (&context_saved);
  92.    
  93.    if (status == PASSED)
  94.    {
  95.       /********************************************************/
  96.       /* Add up the number of 16K pages that are unallocated. */
  97.       /********************************************************/
  98.  
  99.       status = get_unalloc_page_count (&num_unalloc_pages);
  100.       if (status == PASSED)
  101.       {
  102.          *size += PAGE_SIZE * (long) num_unalloc_pages;
  103.       }
  104.  
  105.       /***************************************************/
  106.       /* Go through entire directory one page at a time. */
  107.       /***************************************************/
  108.  
  109.       for (dir_page = 0; ((status == PASSED) && 
  110.                          (dir_page < dir_page_count)); dir_page++)
  111.       {
  112.          /***********************************/
  113.          /* Map in the this directory page. */
  114.          /***********************************/
  115.  
  116.          status = map_dir_page (dir_page, FIRST_PHYS_PAGE);
  117.          if (status == PASSED)
  118.          {
  119.             /******************************************/
  120.             /* Add up all freed blocks for this page. */
  121.             /******************************************/
  122.  
  123.             for (index = 0; (index < DIR_ENTRIES_PER_PAGE); index++)
  124.             {
  125.                if (directory[0][index].token == UNASSIGNED_TOKEN)
  126.                   *size += directory[0][index].size;
  127.             }
  128.          }
  129.       }
  130.    }
  131.    /**************************************************************/
  132.    /* Unmap the directory - remap the pages that were in before. */
  133.    /**************************************************************/
  134.  
  135.     if (context_saved)
  136.        status = restore_memlib_context (status);
  137.  
  138.    /*************************************/
  139.    /* If some error return a size of 0. */
  140.    /*************************************/
  141.  
  142.    if (status != PASSED)
  143.       *size = 0;
  144.  
  145.    return (status);
  146.  
  147. }  /** end of ememavl **/
  148.  
  149. /*$PAGE*/
  150. /**********************************************************************/
  151. /*                                                                    */
  152. /*     Name:    unsigned int ememmax (*size)                          */
  153. /*              unsigned int *size;                                   */
  154. /*                                                                    */
  155. /*     Description:                                                   */
  156. /*        Computes the size of the largest block of expanded memory   */
  157. /*     that MEMLIB can allocate.                                      */
  158. /*                                                                    */
  159. /*     Parameters:                                                    */
  160. /*        output  size  The size of the largest allocatable block.    */
  161. /*                                                                    */
  162. /*     Results returned:                                              */
  163. /*        PASSED     Operation successful                             */
  164. /*        error      Non-zero value, see "ERRORS.H" or EMS table A-2  */
  165. /*                                                                    */
  166. /*     Calling sequence:                                              */
  167. /*     #include "memlib.h"                                            */
  168. /*     #include "errors.h"                                            */
  169. /*         ...                                                        */
  170. /*     unsigned int size;                                             */
  171. /*     unsigned int status;                                           */
  172. /*         ...                                                        */
  173. /*     status = ememmax (&size);                                      */
  174. /*     if (status == PASSED)                                          */
  175. /*         printf("Largest block available = %u \n", size);           */
  176. /*     else                                                           */
  177. /*         { error condition }                                        */
  178. /*                                                                    */
  179. /*     Calls: prepare_dir_mapping()                                   */
  180. /*            map_dir_page()                                          */
  181. /*            get_unalloc_page_count()                                */
  182. /*            restore_memlib_context()                                */
  183. /*                                                                    */
  184. /*     Called by:  Application                                        */
  185. /*                                                                    */
  186. /*     Globals referenced/modified: directory                         */
  187. /*                                  dir_page_count                    */
  188. /*                                                                    */
  189. /**********************************************************************/
  190.  
  191. unsigned int ememmax (size)
  192. unsigned int *size;
  193. {
  194.    unsigned int status;     /* The status of EMM and MEMLIB   */
  195.    unsigned int num_pages;  /* Number of unallocated pages    */
  196.    unsigned int page;       /* Directory page to map in       */
  197.    unsigned int index;      /* Index into a directory page    */
  198.    unsigned int saved;      /* whether the context was saved  */
  199.  
  200.    /**********************************************/
  201.    /* Call prepare_dir_mapping() to save context */
  202.    /* before mapping in the directory            */
  203.    /**********************************************/
  204.  
  205.    status = prepare_dir_mapping (&saved);
  206.  
  207.    if (status == PASSED)
  208.    {
  209.       /***************************************************************/
  210.       /* If more than 64K worth of unallocated pages, set max to     */
  211.       /* the largest allocateable block (64K-1).  Otherwise, test    */
  212.       /* the number of unallocated pages * 16K against *size.        */
  213.       /***************************************************************/
  214.  
  215.       status = get_unalloc_page_count (&num_pages);
  216.       if (status == PASSED)
  217.       {
  218.          if (num_pages >= MAX_ALLOCATABLE_PAGES)
  219.             *size = LARGEST_ALLOCATABLE_BLOCK;
  220.          else 
  221.             *size = PAGE_SIZE * num_pages;
  222.       }
  223.    }
  224.  
  225.    /**************************************/
  226.    /* Go through all the directory pages */
  227.    /**************************************/
  228.  
  229.    for (page = 0; ((status == PASSED) &&
  230.                    (page < dir_page_count)); page++)
  231.    {
  232.       /***********************************/
  233.       /* Map in the this directory page. */
  234.       /***********************************/
  235.  
  236.       status = map_dir_page (page, FIRST_PHYS_PAGE);
  237.       if (status == PASSED)
  238.       {
  239.          /********************************/
  240.          /* Find the maximum free block. */
  241.          /********************************/
  242.  
  243.          for (index = 0; index < DIR_ENTRIES_PER_PAGE; index++)
  244.          {
  245.             if ((directory[0][index].token == UNASSIGNED_TOKEN) && 
  246.                 (directory[0][index].size > *size))
  247.                *size = directory[0][index].size;
  248.          }
  249.       }
  250.    }
  251.  
  252.    /**************************************************************/
  253.    /* Unmap the directory - remap the pages that were in before. */
  254.    /**************************************************************/
  255.  
  256.     if (saved) 
  257.        status = restore_memlib_context (status);
  258.  
  259.    /*************************************/
  260.    /* If some error return a size of 0. */
  261.    /*************************************/
  262.  
  263.    if (status != PASSED)
  264.       *size = 0;
  265.  
  266.    return (status);
  267.  
  268. }  /** end of ememmax **/
  269.  
  270. /*$PAGE*/
  271. /**********************************************************************/
  272. /*                                                                    */
  273. /*     Name:    unsigned int emsize (token, *size)                    */
  274. /*              unsigned int token;                                   */
  275. /*              unsigned int *size;                                   */
  276. /*                                                                    */
  277. /*     Description:                                                   */
  278. /*        Returns the size, in bytes, of the allocated block of       */
  279. /*     memory identified by 'token.' (A token returned from           */
  280. /*     efmalloc).                                                     */
  281. /*                                                                    */
  282. /*     Parameters:                                                    */
  283. /*        input   token       identifies the block desired            */
  284. /*        output  size        the size, in bytes, of the block        */
  285. /*                                                                    */
  286. /*     Results returned:                                              */
  287. /*        PASSED     Operation successful                             */
  288. /*        error      Non-zero value, see "ERRORS.H" or EMS table A-2  */
  289. /*                                                                    */
  290. /*     Calling sequence:                                              */
  291. /*     #include "memlib.h"                                            */
  292. /*     #include "errors.h"                                            */
  293. /*         ...                                                        */
  294. /*     unsigned int status;                                           */
  295. /*     unsigned int token;                                            */
  296. /*     unsigned int size;                                             */
  297. /*                                                                    */
  298. /*     status = efmalloc (200, &token);                               */
  299. /*         ...                                                        */
  300. /*     status = emsize (token, &size);                                */
  301. /*     if (status == PASSED)                                          */
  302. /*         printf ("Size of block = %u bytes\n", size);               */
  303. /*                                                                    */
  304. /*     Calls: prepare_dir_mapping()                                   */
  305. /*            map_dir_page()                                          */
  306. /*            check_token()                                           */
  307. /*            restore_memlib_context()                                */
  308. /*                                                                    */
  309. /*     Called by:  Application                                        */
  310. /*                                                                    */
  311. /*     Globals referenced/modified: directory                         */
  312. /*                                                                    */
  313. /**********************************************************************/
  314.  
  315. unsigned int emsize (token, size)
  316. unsigned int token;
  317. unsigned int *size;
  318. {
  319.    unsigned int status;        /* The status of EMM and MEMLIB    */
  320.    unsigned int page;          /* Directory page to map in        */
  321.    unsigned int index;         /* The index into a directory page */
  322.    unsigned int context_saved; /* Whether the context was saved   */
  323.  
  324.    /**********************************************/
  325.    /* Call prepare_dir_mapping() to save context */
  326.    /* before mapping in the directory            */
  327.    /**********************************************/
  328.  
  329.    status = prepare_dir_mapping (&context_saved);
  330.  
  331.    /***************************/
  332.    /* Check for a valid token */
  333.    /***************************/
  334.  
  335.    if (status == PASSED)
  336.       status = check_token (token);
  337.  
  338.    if (status == PASSED)
  339.    {
  340.       /*****************************************************/
  341.       /* Set 'page' to the directory page this token is in */
  342.       /*****************************************************/
  343.  
  344.       page = token / DIR_ENTRIES_PER_PAGE;
  345.  
  346.       /**********************************************/
  347.       /* Convert the token into an index that falls */
  348.       /* within the size of a directory page        */
  349.       /**********************************************/
  350.  
  351.       index = token % DIR_ENTRIES_PER_PAGE;
  352.  
  353.       /******************************/
  354.       /* Map in this directory page */
  355.       /******************************/
  356.  
  357.       status = map_dir_page (page, FIRST_PHYS_PAGE);
  358.       if (status == PASSED)
  359.       {
  360.          /*****************************/
  361.          /* Check size for this index */
  362.          /*****************************/
  363.  
  364.          if (directory[0][index].token == token)
  365.          {
  366.             *size = directory[0][index].size;
  367.             status = PASSED;
  368.          }
  369.          else
  370.          {
  371.             *size = 0;
  372.             status = INVALID_TOKEN;
  373.          }
  374.       }
  375.    }
  376.  
  377.    /*************************************************************/
  378.    /* Unmap the directory - remap the pages that were in before */
  379.    /*************************************************************/
  380.  
  381.    if (context_saved)
  382.        status = restore_memlib_context (status);
  383.  
  384.    /************************************/
  385.    /* If some error return a size of 0 */
  386.    /************************************/
  387.  
  388.    if (status != PASSED)
  389.       *size = 0;
  390.  
  391.    return (status);
  392.  
  393. }  /** end of emsize **/
  394.  
  395. /*$PAGE*/
  396. /**********************************************************************/
  397. /*                                                                    */
  398. /*     Name:    unsigned int efmalloc (size, token);                  */
  399. /*              unsigned int size;                                    */
  400. /*              unsigned int *token;                                  */
  401. /*                                                                    */
  402. /*     Description:                                                   */
  403. /*        This function is analagous to fmalloc except it allocates a */
  404. /*     block of memory from the expanded memory pool.                 */
  405. /*                                                                    */
  406. /*     Parameters:                                                    */
  407. /*        input    size   The desired size, in bytes, of the block of */
  408. /*                        memory.                                     */
  409. /*        output   token  A tag needed for subsequent calls to the C  */
  410. /*                        Memory Manager to unquiely identify the     */
  411. /*                        block of memory allocated.                  */
  412. /*                                                                    */
  413. /*     Results returned:                                              */
  414. /*        PASSED    Operation successful                              */
  415. /*        error     Non-zero value, see "ERRORS.H" or EMS table A-2   */
  416. /*                                                                    */
  417. /*     Calling sequence:                                              */
  418. /*     #include "memlib.h"                                            */
  419. /*     #include "errors.h"                                            */
  420. /*         ...                                                        */
  421. /*     unsigned int token;                                            */
  422. /*     unsigned int size;                                             */
  423. /*     unsigned int status                                            */
  424. /*         ...                                                        */
  425. /*     size = 100;                                                    */
  426. /*     status = efmalloc (size, &token);                              */
  427. /*     if (status == PASSED)                                          */
  428. /*        { continue normal code - we have allocated space to }       */
  429. /*        { store 100 byte values                             }       */
  430. /*     else                                                           */
  431. /*        { error condition }                                         */
  432. /*                                                                    */
  433. /*     Calls: allocate_new_block()                                    */
  434. /*            check_best_fit()                                        */
  435. /*            prepare_dir_mapping()                                   */
  436. /*            restore_memlib_context()                                */
  437. /*            split_block()                                           */
  438. /*            map_dir_page()                                          */
  439. /*                                                                    */
  440. /*     Called by:  Application                                        */
  441. /*                                                                    */
  442. /*     Globals reference/modified: directory                          */
  443. /*                                 directory_map                      */
  444. /*                                                                    */
  445. /**********************************************************************/
  446.  
  447. unsigned int efmalloc (size, token)
  448. unsigned int size;
  449. unsigned int *token;
  450.  
  451. {
  452.    unsigned int found_block;       /* memory block found                */
  453.    unsigned int status;            /* Status of EMM and MEMLIB          */
  454.    unsigned int best_indexs_page;  /* best_index's dir entry's log page */
  455.    unsigned int best_indexs_index; /* best_index's index into its page  */
  456.    unsigned int best_index;        /* Index of the current best fit     */
  457.    unsigned int context_saved;     /* whether the context was saved     */
  458.    long         min_difference;    /* Minimum difference - best size    */
  459.  
  460.    /**********************************************/
  461.    /* Attempting to allocate 0 bytes is an error */
  462.    /**********************************************/
  463.  
  464.    if (size > 0)
  465.       status = PASSED;
  466.    else
  467.       status = REQUEST_FOR_ZERO_LENGTH_BLOCK;
  468.  
  469.    /**********************************************/
  470.    /* Call prepare_dir_mapping() to save context */
  471.    /* before mapping in the directory            */
  472.    /**********************************************/
  473.  
  474.    if (status == PASSED)
  475.       status = prepare_dir_mapping (&context_saved);
  476.  
  477.    if (status == PASSED)
  478.    {
  479.       /*************************************/
  480.       /* check to see if there exists a    */
  481.       /* "best size" fit in memory blocks. */
  482.       /*************************************/
  483.  
  484.       status = check_best_fit (size, &best_index, &min_difference);
  485.  
  486.       /********************************************/
  487.       /* If best_index is not an UNASSIGNED_TOKEN */
  488.       /* then we found a block.                   */
  489.       /********************************************/
  490.  
  491.       if ((status == PASSED) && 
  492.           (best_index != UNASSIGNED_TOKEN))
  493.       {
  494.          found_block = TRUE;
  495.  
  496.          /****************************************************/
  497.          /* We're going to use a free block to put our block */
  498.          /* into.  First we need to map in the free block's  */
  499.          /* (best_index) directory entry's logical page.     */
  500.          /****************************************************/
  501.  
  502.          /******************************************************************/
  503.          /* Convert best_index to its respective directory page and index. */
  504.          /******************************************************************/
  505.  
  506.          best_indexs_page  = best_index / DIR_ENTRIES_PER_PAGE;
  507.          best_indexs_index = best_index % DIR_ENTRIES_PER_PAGE;
  508.  
  509.          /***************************************/
  510.          /* Map in best_index's directory page. */
  511.          /***************************************/
  512.  
  513.          status = map_dir_page (best_indexs_page, FIRST_PHYS_PAGE);
  514.  
  515.  
  516.          /********************************************************/
  517.          /* If the size of the best fit that we found was 0 then */
  518.          /* what we found was an unallocated block.  Allocate a  */
  519.          /* a new block.                                         */
  520.          /********************************************************/
  521.  
  522.          if (directory[0][best_indexs_index].size == 0)
  523.             status = allocate_new_block (size, best_index);
  524.          else
  525.          {
  526.             /******************************************************/
  527.             /* When using a previously allocated block we need to */
  528.             /* check the size and if any space is left over we    */
  529.             /* should make a new available block.                 */
  530.             /******************************************************/
  531.  
  532.             if ((status == PASSED) && 
  533.                 (min_difference != 0))
  534.             {
  535.                status = split_block (best_index, size);
  536.             } 
  537.  
  538.          } /** end else **/
  539.  
  540.       }  /** end if best_index ... **/
  541.  
  542.    }   /** end if passed from prepare_dir_mapping() **/
  543.  
  544.    /********************************************************/
  545.    /* We found a block - set the token value and directory */
  546.    /* entries.  (The directory pointer (offset) is set     */
  547.    /* either in allocate_new_block or was already valid.)  */
  548.    /********************************************************/
  549.    if (status == PASSED)
  550.    {
  551.       if (found_block) 
  552.       {
  553.          status = map_dir_page (best_indexs_page, FIRST_PHYS_PAGE);
  554.          if (status == PASSED)
  555.          {
  556.             *token = best_index;
  557.             directory[0][best_indexs_index].token = best_index;
  558.             directory[0][best_indexs_index].size  = size;
  559.          }
  560.       }
  561.       else
  562.       {
  563.          *token = UNASSIGNED_TOKEN;
  564.          if (!found_block)
  565.             status = TOO_MANY_DIRECTORY_ENTRIES;
  566.       }
  567.    }
  568.  
  569.    /*************************************************************/
  570.    /* Unmap the directory - remap the pages that were in before */
  571.    /*************************************************************/
  572.  
  573.    if (context_saved)
  574.        status = restore_memlib_context (status);
  575.  
  576.    return (status);
  577.  
  578. }  /** end efmalloc **/
  579.  
  580. /*$PAGE*/
  581. /**********************************************************************/
  582. /*                                                                    */
  583. /*     Name:  unsigned int effree (token)                             */
  584. /*            unsigned int token;                                     */
  585. /*                                                                    */
  586. /*     Description:                                                   */
  587. /*        This function frees a block of memory from expanded memory  */
  588. /*     that was allocated by efmalloc().                              */
  589. /*                                                                    */
  590. /*     Parameters:                                                    */
  591. /*        input  token  The token returned by efmalloc when this      */
  592. /*                      block was allocated.                          */
  593. /*                                                                    */
  594. /*     Results returned:                                              */
  595. /*        PASSED    Operation successful                              */
  596. /*        error     Non-zero value, see "ERRORS.H" or EMS table A-2   */
  597. /*                                                                    */
  598. /*     Calling sequence:                                              */
  599. /*     #include "memlib.h"                                            */
  600. /*     #include "errors.h"                                            */
  601. /*         ...                                                        */
  602. /*     unsigned int token;                                            */
  603. /*     unsigned int status;                                           */
  604. /*         ...                                                        */
  605. /*     status = efmalloc (100, &token);                               */
  606. /*         ...                                                        */
  607. /*     status = efree(token);                                         */
  608. /*     if (status == PASSED)                                          */
  609. /*        { continue normal code }                                    */
  610. /*     else                                                           */
  611. /*        { error condition }                                         */
  612. /*                                                                    */
  613. /*     Calls: check_if_all_blocks_free()                              */
  614. /*            check_token()                                           */
  615. /*            prepare_dir_mapping()                                   */
  616. /*            restore_memlib_context()                                */
  617. /*            search_after()                                          */
  618. /*            search_before()                                         */
  619. /*            map_dir_page()                                          */
  620. /*            effreeall()                                             */
  621. /*                                                                    */
  622. /*     Called by: Application                                         */
  623. /*                                                                    */
  624. /*     Globals referenced/modified: directory                         */
  625. /*                                  dir_start                         */
  626. /*                                                                    */
  627. /**********************************************************************/
  628.  
  629. unsigned int effree (token)
  630. unsigned int token;
  631. {
  632.    unsigned int status;             /* Status of EMM and MEMLIB           */
  633.    unsigned int all_blocks_free;    /* Whether all blocks are free or not */
  634.    unsigned int j;                  /* Looping variable                   */
  635.    unsigned int usable_entry;       /* A usuable directory entry          */
  636.    unsigned int size_mod_page_size; /* Size of a block MOD PAGE_SIZE      */
  637.    unsigned int tokens_index;       /* Token's index into its log page    */
  638.    unsigned int tokens_page;        /* Token's dir entry's logical page   */
  639.    unsigned int usable_entrys_index;/* Usable_entry's index into its page */
  640.    unsigned int usable_entrys_page; /* Usable_entry's dir entry's log page*/
  641.    unsigned int final_entrys_index; /* Final_entry's index into its page  */
  642.    unsigned int final_entrys_page;  /* Final_entry's dir entry's log page */
  643.    unsigned int final_entry;        /* Directory entry of the final       */
  644.                                     /* coalesced block                    */
  645.    unsigned int context_saved;      /* Whether the context was saved      */
  646.  
  647.    /******************************/
  648.    /* Initialize some variables. */
  649.    /******************************/
  650.  
  651.    all_blocks_free = FALSE;
  652.    context_saved   = FALSE;
  653.    
  654.    /******************************/
  655.    /* Check for an invalid token */
  656.    /******************************/
  657.  
  658.    status = check_token (token);
  659.  
  660.    /**********************************************/
  661.    /* Call prepare_dir_mapping() to save context */
  662.    /* before mapping in the directory            */
  663.    /**********************************************/
  664.    if (status == PASSED)
  665.       status = prepare_dir_mapping (&context_saved);
  666.  
  667.    if (status == PASSED)         
  668.    {
  669.       /************************************************/
  670.       /* Convert token to its index and logical page. */
  671.       /************************************************/
  672.  
  673.       tokens_index = token % DIR_ENTRIES_PER_PAGE;
  674.       tokens_page  = token / DIR_ENTRIES_PER_PAGE;
  675.  
  676.       /*******************************/
  677.       /* Map in this directory page. */
  678.       /*******************************/
  679.  
  680.       status = map_dir_page (tokens_page, FIRST_PHYS_PAGE);
  681.    }
  682.  
  683.    if (status == PASSED)
  684.    {
  685.       /*************************************************/
  686.       /* If token does not identify an allocated block */
  687.       /* or if its size is zero return an error code.  */
  688.       /*************************************************/
  689.  
  690.       if ((directory[0][tokens_index].token != token) ||
  691.           (directory[0][tokens_index].size == 0))
  692.          status = INVALID_TOKEN;
  693.  
  694.       if (status == PASSED)
  695.       {
  696.          /*******************************************************/
  697.          /* Set token to UNASSIGNED_TOKEN showing freed status. */
  698.          /*******************************************************/
  699.  
  700.          directory[0][tokens_index].token = UNASSIGNED_TOKEN;
  701.  
  702.          /****************************************************/
  703.          /* If this token is less than the current starting  */
  704.          /* location then set the new starting location used */
  705.          /* when searching for free directory entries.       */
  706.          /****************************************************/
  707.  
  708.          if (token < dir_start)
  709.             dir_start = token;
  710.  
  711.          /**********************************/
  712.          /* Check if all pages are free.   */
  713.          /* If not, try to coalesce blocks */
  714.          /**********************************/
  715.  
  716.          status = check_if_all_blocks_free (&all_blocks_free);
  717.       }
  718.       if ((status == PASSED) &&
  719.           (all_blocks_free))
  720.       {
  721.          /*****************************************/
  722.          /* We need to restore the context before */
  723.          /* the pages and handles.                */
  724.          /*****************************************/
  725.  
  726.          if (context_saved)
  727.              status = restore_memlib_context (status);
  728.  
  729.          if (status == PASSED)
  730.          {
  731.             context_saved = FALSE;
  732.             status = effreeall();
  733.          }
  734.       }
  735.       else if ((status == PASSED) &&
  736.                (!all_blocks_free)) 
  737.       {
  738.          /*****************************************************/
  739.          /* Search for a free block of memory after this free */
  740.          /* block to coalesce into one free block.  This      */
  741.          /* makes sure that if there are a number of little   */
  742.          /* blocks that could actually be put together into   */
  743.          /* one large block that we do so.                    */
  744.          /*****************************************************/
  745.  
  746.          status = search_after (token, &final_entry, &usable_entry);
  747.  
  748.          /*******************************************************/
  749.          /* Search for a free block of memory before this block */
  750.          /* to coalesce into one free block.                    */
  751.          /*******************************************************/
  752.  
  753.          if (status == PASSED)
  754.             status = search_before (token, &final_entry, &usable_entry);
  755.  
  756.          /**************************************************/
  757.          /* Test to see if we coalesced any blocks.  If so */
  758.          /* we need to check that the coalesced block does */
  759.          /* not overlap too many logical pages.            */
  760.          /**************************************************/
  761.          
  762.          if ((status == PASSED) &&
  763.              (final_entry != UNASSIGNED_TOKEN)) 
  764.          {
  765.             /*****************************************/
  766.             /* Convert final_entry to its respective */
  767.             /* directory page and index.             */
  768.             /*****************************************/
  769.  
  770.             final_entrys_page  = final_entry / DIR_ENTRIES_PER_PAGE;
  771.             final_entrys_index = final_entry % DIR_ENTRIES_PER_PAGE;
  772.    
  773.             /****************************************/
  774.             /* Map in final_entry's directory page. */
  775.             /****************************************/
  776.  
  777.             status = map_dir_page (final_entrys_page, FIRST_PHYS_PAGE);
  778.             if (status == PASSED)
  779.             {
  780.                /*******************************************************/
  781.                /* We can't have a block taking up more logical pages  */
  782.                /* than it needs.  We always guarantee that a block of */
  783.                /* memory take the least amount of logical pages as    */
  784.                /* possible.  If it overlaps too many blocks we need   */
  785.                /* to break it up.  Check the block final_index for    */
  786.                /* too much overlap.                                   */
  787.                /*******************************************************/
  788.    
  789.                size_mod_page_size = 
  790.                               directory[0][final_entrys_index].size % PAGE_SIZE;
  791.                if (size_mod_page_size == 0)
  792.                   size_mod_page_size = PAGE_SIZE;
  793.  
  794.                if ((PAGE_SIZE - directory[0][final_entrys_index].offset) <
  795.                    size_mod_page_size)
  796.    
  797.                {
  798.                   /*********************************************************/
  799.                   /* Convert usable_block to its respective directory page */
  800.                   /* and index.  We're going to map this page into the     */
  801.                   /* second physical page.                                 */
  802.                   /*********************************************************/
  803.  
  804.                   usable_entrys_page  = usable_entry / DIR_ENTRIES_PER_PAGE;
  805.                   usable_entrys_index = usable_entry % DIR_ENTRIES_PER_PAGE;
  806.  
  807.                   /****************************************************/
  808.                   /* Map in usable_block's directory page using the   */
  809.                   /* directory_map's second array element to map this */
  810.                   /* page in at physical page one while keeping the   */
  811.                   /* block that was coalesced's directory page at     */
  812.                   /* physical page zero.                              */
  813.                   /***************************************************/
  814.  
  815.                   status = map_dir_page (usable_entrys_page, SECOND_PHYS_PAGE);
  816.  
  817.                   /*************************************************/
  818.                   /* This block overlaps too many logical pages.   */
  819.                   /* We need to break it into two pieces at a      */
  820.                   /* a logical page boundry.  Use the usable_block */
  821.                   /* set when coalescing.                          */
  822.                   /*************************************************/
  823.  
  824.                   if (status == PASSED)
  825.                   {
  826.                      /*************************************************/
  827.                      /* Set the second block's (usable_entry) size to */
  828.                      /* the size of the first piece after the first   */
  829.                      /* page boundry of the whole block.              */
  830.                      /*************************************************/
  831.                      
  832.                      directory[1][usable_entrys_index].size =
  833.                         directory[0][final_entrys_index].size -
  834.                         PAGE_SIZE + directory[0][final_entrys_index].offset;
  835.  
  836.                      /**************************************/
  837.                      /* Set the offset of the second block */
  838.                      /* to start at the page boundry.      */
  839.                      /**************************************/
  840.  
  841.                      directory[1][usable_entrys_index].offset = 0;
  842.                 
  843.                      /***********************************************/
  844.                      /* Set the logical pages for the second block. */
  845.                      /***********************************************/
  846.  
  847.                      for (j = 0; j < NUM_PAGES (directory[1][usable_entrys_index].size); j++)
  848.                      {
  849.                         directory[1][usable_entrys_index].logical_page[j] =
  850.                            directory[0][final_entrys_index].logical_page[j + 1];
  851.                      }
  852.  
  853.                      /***********************************************/
  854.                      /* Set the first block size to the amount of   */
  855.                      /* memory before the logical page boundry (the */
  856.                      /* space before the second block).             */
  857.                      /***********************************************/
  858.  
  859.                      directory[0][final_entrys_index].size -=
  860.                         directory[1][usable_entrys_index].size;
  861.                   }
  862.  
  863.                } /** end if PAGE_SIZE ... **/
  864.    
  865.             } /** status passed **/
  866.                
  867.          } /** end if final_index ... **/
  868.             
  869.       } /** end if check_of_all_blocks_free **/
  870.          
  871.    } /** end if status passed **/
  872.  
  873.    /*************************************************************/
  874.    /* Unmap the directory - remap the pages that were in before */
  875.    /*************************************************************/
  876.  
  877.    if ((!all_blocks_free) &&
  878.        (context_saved))
  879.        status = restore_memlib_context (status);
  880.  
  881.    return (status);
  882.  
  883. } /** end effree **/
  884.  
  885. /*$PAGE*/
  886. /**********************************************************************/
  887. /*                                                                    */
  888. /*     Name:  unsigned int seteptrs (num_blocks, token, pointer)      */              
  889. /*            unsigned int num_blocks;                                */
  890. /*            unsigned int token[];                                   */
  891. /*            void far*    pointer[];                                 */
  892. /*                                                                    */
  893. /*     Description:                                                   */
  894. /*        Attempts to map all the pages required by the block(s) of   */
  895. /*     memory identified by token[].  Returns pointers to each block  */
  896. /*     that has been mapped in.  If the requested block(s) could not  */
  897. /*     mapped in then we return an error.                             */
  898. /*                                                                    */
  899. /*     Parameters:                                                    */
  900. /*        input  num_blocks          Number of blocks to get access   */
  901. /*                                   to.                              */
  902. /*        input  token[num_blocks]   An array of tokens that identify */
  903. /*                                   the blocks to be mapped in. (The */
  904. /*                                   tokens returned by efmalloc when */
  905. /*                                   the block(s) were allocated.)    */
  906. /*        output pointer[num_blocks] An array of far pointers returned*/
  907. /*                                   to the application.  Pointer[i]  */
  908. /*                                   will point to the block of       */
  909. /*                                   memory identified by token[i].   */
  910. /*                                                                    */
  911. /*     Results returned:                                              */
  912. /*        PASSED    Operation successful                              */
  913. /*        error     Non-zero value, see "ERRORS.H" or EMS table A-2   */
  914. /*                                                                    */
  915. /*     Calling sequence:                                              */
  916. /*     #include "memlib.h"                                            */
  917. /*     #include "errors.h"                                            */
  918. /*         ...                                                        */
  919. /*     void far*    pointers[2];                                      */
  920. /*     unsigned int tokens[2];                                        */
  921. /*     unsigned int status;                                           */
  922. /*         ...                                                        */
  923. /*     status = efmalloc (200, &token[0]);                            */
  924. /*     if (status != PASSED)                                          */
  925. /*        { error condition }                                         */
  926. /*     else                                                           */
  927. /*        { continue normal code }                                    */
  928. /*         ...                                                        */
  929. /*     status = efmalloc (600, &token[1]);                            */
  930. /*     if (status != PASSED)                                          */
  931. /*        { error condition }                                         */
  932. /*     else                                                           */
  933. /*        { continue normal code }                                    */
  934. /*         ...                                                        */
  935. /*     status = seteptrs (2, tokens, pointers)                        */
  936. /*     if (status == PASSED)                                          */
  937. /*       { blocks mapped in - use pointers to reference them }        */
  938. /*     else                                                           */
  939. /*       { error - a token was bad or not all blocks could fit }      */
  940. /*                                                                    */
  941. /*     Calls: map_dir_page()                                          */
  942. /*            map_unmap_pages()                                       */
  943. /*                                                                    */
  944. /*     Called by: Application                                         */
  945. /*                set1eptr()                                          */
  946. /*                set2eptrs()                                         */
  947. /*                set3eptrs()                                         */
  948. /*                                                                    */
  949. /*     Globals referenced/modified: directory                         */
  950. /*                                  app_handle                        */
  951. /*                                  directory_map                     */
  952. /*                                  num_pages_in_page_frame           */
  953. /*                                  number_pages_mapped               */
  954. /*                                  page_frame_base_address           */
  955. /*                                  pages_mapped                      */
  956. /*                                                                    */
  957. /**********************************************************************/
  958.  
  959. unsigned int seteptrs (num_blocks, token, pointer)
  960. unsigned int num_blocks;
  961. unsigned int token[];   
  962. void far*    pointer[];
  963. {
  964.    unsigned int status;             /* Status of EMM & MEMLIB               */
  965.    unsigned int i;                  /* looping variable                     */
  966.    unsigned int j;                  /* looping variable                     */
  967.    unsigned int start_phys_page;    /* Starting physical page in page frame */
  968.    unsigned int log_page_match;     /* Match was found? TRUE/FALSE          */
  969.    unsigned int log_page;           /* temporarily store log page we're on  */
  970.    unsigned int current_dir_page;   /* The current directory page mapped in */
  971.    unsigned int tokens_page;        /* Token's dir entry's logical page     */
  972.    unsigned int tokens_index;       /* Token's index into its logical page  */
  973.    unsigned int num_pages_for_token;/* Number of logical pages for token's  */
  974.                                     /* block                                */
  975.    void far*    tokens_ptr;         /* pointer to token's block             */
  976.                                  
  977.    /*******************************/
  978.    /* Initialize local variables. */
  979.    /*******************************/
  980.  
  981.    status = PASSED;
  982.    current_dir_page = UNMAPPED;
  983.  
  984.    /***************************************/
  985.    /* Make sure all the tokens are valid. */
  986.    /***************************************/
  987.  
  988.    for (i = 0; ((status == PASSED) &&
  989.                 (i < num_blocks)); i++)
  990.    {
  991.       status = check_token (token[i]);
  992.    }
  993.  
  994.    if (status == PASSED)
  995.    {
  996.       /*******************************************************/
  997.       /* Set each page in the page frame to UNMAPPED status. */
  998.       /*******************************************************/
  999.  
  1000.       for (i = 0; i < num_pages_in_page_frame; i++)
  1001.          pages_mapped[i].log_page = UNMAPPED;
  1002.  
  1003.       number_pages_mapped = 0;
  1004.  
  1005.       /***********************************************/
  1006.       /* For each block requested, try to map it in. */
  1007.       /***********************************************/
  1008.  
  1009.       for (i = 0; ((status == PASSED) &&
  1010.                    (i < num_blocks)); i++)
  1011.       {
  1012.          tokens_page  = token[i] / DIR_ENTRIES_PER_PAGE;
  1013.          tokens_index = token[i] % DIR_ENTRIES_PER_PAGE;
  1014.  
  1015.          if (tokens_page != current_dir_page)
  1016.          {
  1017.             current_dir_page = tokens_page;
  1018.             status = map_dir_page (current_dir_page, FIRST_PHYS_PAGE);
  1019.          }
  1020.          
  1021.          if ((status == PASSED) &&
  1022.              (token[i] != directory[0][tokens_index].token))
  1023.             status = INVALID_TOKEN;
  1024.  
  1025.          if (status == PASSED)
  1026.          {
  1027.             /*********************************/
  1028.             /* Initialize variable for loop. */
  1029.             /*********************************/
  1030.  
  1031.             start_phys_page      = 0;
  1032.             log_page_match       = FALSE;
  1033.             num_pages_for_token  = NUM_PAGES (directory[0][tokens_index].size);
  1034.  
  1035.             /***********************************************************/
  1036.             /* While there's potentially room to map the logical pages */
  1037.             /* need for the i'th block and it isn't already mapped in. */          
  1038.             /***********************************************************/
  1039.  
  1040.             while (((start_phys_page + num_pages_for_token) 
  1041.                      <= num_pages_in_page_frame) 
  1042.                    && (!log_page_match))
  1043.             {
  1044.                /*****************************************/
  1045.                /* Assume the logical pages need for the */
  1046.                /* i'th block are already mapped in.     */
  1047.                /*****************************************/
  1048.  
  1049.                log_page_match = TRUE;
  1050.  
  1051.                /**************************************************/
  1052.                /* Test each of the logical pages in the i'th     */
  1053.                /* block against the logical pages already mapped */
  1054.                /* in the page frame starting at start_phys_page. */
  1055.                /**************************************************/
  1056.  
  1057.                for (j = 0; (j < num_pages_for_token); j++)
  1058.                {
  1059.                   log_page = directory[0][tokens_index].logical_page[j];
  1060.  
  1061.                   /**********************************************/
  1062.                   /* We won't have a match if the logical page  */
  1063.                   /* we're looking for is not already mapped in */
  1064.                   /* and if the page is unmapped.               */
  1065.                   /**********************************************/
  1066.  
  1067.                   if ((log_page != pages_mapped[start_phys_page + j].log_page) &&
  1068.                       (pages_mapped[start_phys_page + j].log_page != UNMAPPED))
  1069.                      log_page_match = FALSE;
  1070.                }
  1071.                /*************************************************/
  1072.                /* If the i'th block isn't mapped in (starting   */
  1073.                /* at start_phys_page) increment start_phys_page */
  1074.                /* and try again.                                */
  1075.                /*************************************************/
  1076.  
  1077.                if (!log_page_match)
  1078.                   start_phys_page++;
  1079.  
  1080.             }  /** end while **/
  1081.  
  1082.             /**************************************************/
  1083.             /* If a match was found set pages_mapped array to */
  1084.             /* include the logical pages for this block.  If  */
  1085.             /* no match was found we can't map this block     */
  1086.             /**************************************************/
  1087.  
  1088.             if (log_page_match)
  1089.             {
  1090.                for (j = 0; (j < num_pages_for_token); j++)
  1091.                {
  1092.                   pages_mapped[start_phys_page + j].log_page =
  1093.                      directory[0][tokens_index].logical_page[j];
  1094.  
  1095.                   /*************************************************/
  1096.                   /* Update pointer[i] to point to the i'th block. */
  1097.                   /* The offset of the pointer we return is equal  */
  1098.                   /* to the offset of this block within the first  */
  1099.                   /* logical page for this block.  These pointers  */
  1100.                   /* are only good modulus 16K since, for example, */
  1101.                   /* we could have allocated a block when it was   */
  1102.                   /* mapped in at phys page 0 and now want to map  */
  1103.                   /* it in at phys page 3 or some such.            */
  1104.                   /*************************************************/
  1105.  
  1106.                   FP_OFF (tokens_ptr) = directory[0][tokens_index].offset;
  1107.                   FP_SEG (tokens_ptr) = FP_SEG(page_frame_base_address) +
  1108.                                         start_phys_page * OFFSET_SIZE;
  1109.                   pointer[i]          = tokens_ptr;
  1110.                }
  1111.             }
  1112.             else
  1113.                status = CANNOT_MAP_ALL_BLOCKS;
  1114.  
  1115.          } /** if status PASSED **/
  1116.  
  1117.       }  /** end for i **/
  1118.  
  1119.    }  /** end if status PASSED **/
  1120.  
  1121.    /*************************************************************/
  1122.    /* Unmap the directory - remap the pages that were in before */
  1123.    /*************************************************************/
  1124.  
  1125.    if (status == PASSED)
  1126.    {
  1127.       /*************************************/
  1128.       /* Count the number of pages to map. */
  1129.       /*************************************/
  1130.  
  1131.       number_pages_mapped = 0;
  1132.       for (i = 0; i < num_pages_in_page_frame; i++)
  1133.       {
  1134.          if (pages_mapped[i].log_page != UNMAPPED)
  1135.             number_pages_mapped++;
  1136.       }
  1137.       /************************************/
  1138.       /* Map in all the blocks requested. */
  1139.       /************************************/
  1140.  
  1141.       status = map_unmap_pages (PHYS_PAGE_MODE, number_pages_mapped,
  1142.                                 pages_mapped, app_handle);
  1143.    }
  1144.    return(status);
  1145.  
  1146. } /** end seteptrs **/
  1147.  
  1148. /*$PAGE*/
  1149. /**********************************************************************/
  1150. /*                                                                    */
  1151. /*     Name:  unsigned int set1eptr (token, pointer)                  */
  1152. /*            unsigned int token;                                     */
  1153. /*            void far*    *pointer;                                  */
  1154. /*                                                                    */
  1155. /*     Description:                                                   */
  1156. /*        Convenience routine that calls seteptrs to just get access  */
  1157. /*     to one block.                                                  */
  1158. /*                                                                    */
  1159. /*     Parms Passed:                                                  */
  1160. /*        input  token     A token that identifies the block to be    */
  1161. /*                         mapped in. (The token returned by efmalloc */
  1162. /*                         when the block was allocated.)             */
  1163. /*        output pointer   A far pointer returned to the application. */
  1164. /*                         It will point to the block of memory       */
  1165. /*                         identified by token.                       */
  1166. /*                                                                    */
  1167. /*     Results returned:                                              */
  1168. /*        PASSED     Operation successful                             */
  1169. /*        error     Non-zero value, see "ERRORS.H" or EMS table A-2   */
  1170. /*                                                                    */
  1171. /*     Calling sequence:                                              */
  1172. /*     #include "memlib.h"                                            */
  1173. /*     #include "errors.h"                                            */
  1174. /*         ...                                                        */
  1175. /*     void far*     pointer;                                         */
  1176. /*     unsigned int  token;                                           */
  1177. /*     unsigned int  status;                                          */
  1178. /*         ...                                                        */
  1179. /*     status = efmalloc (500, &token);                               */
  1180. /*     if (status != PASSED)                                          */
  1181. /*        { error condition }                                         */
  1182. /*     else                                                           */
  1183. /*        { continue normal code }                                    */
  1184. /*         ...                                                        */
  1185. /*     status = set1eptr(token, &pointer)                             */
  1186. /*     if (status == PASSED)                                          */
  1187. /*       { block mapped in - use pointer to reference it }            */
  1188. /*     else                                                           */
  1189. /*       { error - the token was invalid }                            */
  1190. /*                                                                    */
  1191. /*     Calls: seteptrs()                                              */
  1192. /*                                                                    */
  1193. /*     Called by: Application                                         */
  1194. /*                                                                    */
  1195. /*     Globals referenced/modified: None                              */
  1196. /*                                                                    */
  1197. /**********************************************************************/
  1198.  
  1199. unsigned int set1eptr (token, pointer)
  1200. unsigned int token;    
  1201. void far*    *pointer;
  1202. {
  1203.    unsigned int tokens[1];     /* Set one array entry to pass to   */
  1204.                                /* seteptrs()                       */
  1205.    void far*    pointers[1];   /* Set one array entry to be passed */
  1206.                                /* back from seteptrs()             */
  1207.    unsigned int status;        /* Status of EMM and MEMLIB         */
  1208.  
  1209.    tokens[0] = token;
  1210.  
  1211.    /**************************************************/
  1212.    /* Call seteptrs() to map in the block identified */
  1213.    /* by token and return it pointer.                */
  1214.    /**************************************************/
  1215.  
  1216.    status = seteptrs (1, tokens, pointers);
  1217.  
  1218.    if (status == PASSED)
  1219.       *pointer = pointers[0];
  1220.  
  1221.    return (status);
  1222.  
  1223. }  /** end set1eptr **/
  1224.  
  1225.  
  1226. /*$PAGE*/
  1227. /**********************************************************************/
  1228. /*                                                                    */
  1229. /*     Name:  unsigned int set2eptrs (token1, token2, pointer1,       */
  1230. /*                                      pointer2)                     */
  1231. /*            unsigned int token1;                                    */
  1232. /*            unsigned int token2;                                    */
  1233. /*            void far*    *pointer1;                                 */
  1234. /*            void far*    *pointer2;                                 */
  1235. /*                                                                    */
  1236. /*     Description:                                                   */
  1237. /*        Convenience routine that calls seteptrs to get access to    */
  1238. /*     two different blocks of memory at one time.                    */
  1239. /*                                                                    */
  1240. /*     Parameters:                                                    */
  1241. /*        input  token1    A token that identifies the first block to */
  1242. /*                         be mapped in. (The token returned by       */
  1243. /*                         efmalloc when the block was allocated.)    */
  1244. /*        input  token2    A token that identifies the second block   */
  1245. /*                         to be mapped in. (The token returned by    */
  1246. /*                         efmalloc when the block was allocated.)    */
  1247. /*        output pointer1  A far pointer returned to the application. */
  1248. /*                         It will point to the block of memory       */
  1249. /*                         identified by token1.                      */
  1250. /*        output pointer2  A far pointer returned to the application. */
  1251. /*                         It will point to the block of memory       */
  1252. /*                         identified by token2.                      */
  1253. /*                                                                    */
  1254. /*     Results returned:                                              */
  1255. /*        PASSED    Operation successful                              */
  1256. /*        error     Non-zero value, see "ERRORS.H" or EMS table A-2   */
  1257. /*                                                                    */
  1258. /*     Calling sequence:                                              */
  1259. /*     #include "memlib.h"                                            */
  1260. /*     #include "errors.h"                                            */
  1261. /*         ...                                                        */
  1262. /*     void far*    ptr1;                                             */
  1263. /*     void far*    ptr2;                                             */
  1264. /*     unsigned int token1;                                           */
  1265. /*     unsigned int token2;                                           */
  1266. /*     unsigned int status;                                           */
  1267. /*         ...                                                        */
  1268. /*     status = efmalloc (500, &token1);                              */
  1269. /*     if (status != PASSED)                                          */
  1270. /*        { error condition }                                         */
  1271. /*     else                                                           */
  1272. /*        { continue normal code }                                    */
  1273. /*         ...                                                        */
  1274. /*     status = efmalloc (900, &token2);                              */
  1275. /*     if (status != PASSED)                                          */
  1276. /*        { error condition }                                         */
  1277. /*     else                                                           */
  1278. /*        { continue normal code }                                    */
  1279. /*         ...                                                        */
  1280. /*     status = set2eptrs (token1, token2, &ptr1, &ptr2);             */
  1281. /*     if (status == PASSED)                                          */
  1282. /*       { blocks mapped in - use pointers to reference them }        */
  1283. /*     else                                                           */
  1284. /*       { error - a token was invalid or blocks couldn't fit }       */
  1285. /*                                                                    */
  1286. /*     Calls: seteptrs()                                              */
  1287. /*                                                                    */
  1288. /*     Called by: Application                                         */
  1289. /*                                                                    */
  1290. /*     Globals referenced/modified: None                              */
  1291. /*                                                                    */
  1292. /**********************************************************************/
  1293.  
  1294. unsigned int set2eptrs (token1, token2, pointer1, pointer2)
  1295. unsigned int token1;                                        
  1296. unsigned int token2;                                        
  1297. void far*    *pointer1;            
  1298. void far*    *pointer2;                                    
  1299. {
  1300.    unsigned int tokens[2];      /* Set two array entries to pass to   */
  1301.                                 /* seteptrs()                         */
  1302.    void far*    pointers[2];    /* Set two array entries to be passed */
  1303.                                 /* back from seteptrs()               */
  1304.    unsigned int status;         /* Status of EMM and MEMLIB           */
  1305.  
  1306.    tokens[0] = token1;
  1307.    tokens[1] = token2;
  1308.  
  1309.    /***************************************************/
  1310.    /* Call seteptrs() to map in the blocks identified */
  1311.    /* by token1 and token2 and return their pointers. */
  1312.    /***************************************************/
  1313.  
  1314.    status = seteptrs (2, tokens, pointers);
  1315.  
  1316.    if (status == PASSED)
  1317.    {
  1318.       *pointer1 = pointers[0];
  1319.       *pointer2 = pointers[1];
  1320.    }
  1321.  
  1322.    return (status);
  1323.  
  1324. }  /** end set2eptrs **/
  1325.  
  1326. /*$PAGE*/
  1327. /**********************************************************************/
  1328. /*                                                                    */
  1329. /*     Name:  unsigned int set3eptrs (token1, token2, token3,         */
  1330. /*                                      pointer1, pointer2, pointer3) */                    
  1331. /*            unsigned int token1;                                    */
  1332. /*            unsigned int token2;                                    */
  1333. /*            unsigned int token3;                                    */
  1334. /*            void far*    *pointer1;                                 */
  1335. /*            void far*    *pointer2;                                 */
  1336. /*            void far*    *pointer3;                                 */
  1337. /*                                                                    */
  1338. /*     Description:                                                   */
  1339. /*        Convenience routine that calls seteptrs to get access to    */
  1340. /*     three different blocks of memory at one time.                  */
  1341. /*                                                                    */
  1342. /*     Parameters:                                                    */
  1343. /*        input  token1    A token that identifies the first block to */
  1344. /*                         be mapped in. (The token returned by       */
  1345. /*                         efmalloc when the block was allocated.)    */
  1346. /*        input  token2    A token that identifies the second block   */
  1347. /*                         to be mapped in. (The token returned by    */
  1348. /*                         efmalloc when the block was allocated.)    */
  1349. /*        input  token3    A token that identifies the third block to */
  1350. /*                         be mapped in. (The token returned by       */
  1351. /*                         efmalloc when the block was allocated.)    */
  1352. /*        output pointer1  A far pointer returned to the application. */
  1353. /*                         It will point to the block of memory       */
  1354. /*                         identified by token1.                      */
  1355. /*        output pointer2  A far pointer returned to the application. */
  1356. /*                         It will point to the block of memory       */
  1357. /*                         identified by token2.                      */
  1358. /*        output pointer3  A far pointer returned to the application. */
  1359. /*                         It will point to the block of memory       */
  1360. /*                         identified by token3.                      */
  1361. /*                                                                    */
  1362. /*     Results returned:                                              */
  1363. /*        PASSED    Operation successful                              */
  1364. /*        error     Non-zero value, see "ERRORS.H" or EMS table A-2   */
  1365. /*                                                                    */
  1366. /*                                                                    */
  1367. /*     Calling sequence:                                              */
  1368. /*     #include "memlib.h"                                            */
  1369. /*     #include "errors.h"                                            */
  1370. /*         ...                                                        */
  1371. /*     void far*    ptr1;                                             */
  1372. /*     void far*    ptr2;                                             */
  1373. /*     void far*    ptr3;                                             */
  1374. /*     unsigned int tok1;                                             */
  1375. /*     unsigned int tok2;                                             */
  1376. /*     unsigned int tok3;                                             */
  1377. /*     unsigned int status;                                           */
  1378. /*         ...                                                        */
  1379. /*     status = efmalloc (500, &tok1);                                */
  1380. /*     if (status != PASSED)                                          */
  1381. /*        { error condition }                                         */
  1382. /*     else                                                           */
  1383. /*        { continue normal code }                                    */
  1384. /*         ...                                                        */
  1385. /*     status = efmalloc (900, &tok2);                                */
  1386. /*     if (status != PASSED)                                          */
  1387. /*        { error condition }                                         */
  1388. /*     else                                                           */
  1389. /*        { continue normal code }                                    */
  1390. /*         ...                                                        */
  1391. /*     status = efmalloc (300, &tok3);                                */
  1392. /*     if (status != PASSED)                                          */
  1393. /*        { error condition }                                         */
  1394. /*     else                                                           */
  1395. /*        { continue normal code }                                    */
  1396. /*         ...                                                        */
  1397. /*     status = set3eptrs (tok1, tok2, tok3, &ptr1, &ptr2, &ptr3);    */
  1398. /*     if (status == PASSED)                                          */
  1399. /*       { blocks mapped in - use pointers to reference them }        */
  1400. /*     else                                                           */
  1401. /*       { error - a token was invalid or blocks couldn't fit }       */
  1402. /*                                                                    */
  1403. /*     Calls: seteptrs()                                              */
  1404. /*                                                                    */
  1405. /*     Called by: Application                                         */
  1406. /*                                                                    */
  1407. /*     Globals referenced/modified: None                              */
  1408. /*                                                                    */
  1409. /**********************************************************************/
  1410.  
  1411. unsigned int set3eptrs (token1, token2, token3, pointer1, pointer2,
  1412.                           pointer3)
  1413. unsigned int token1;                                        
  1414. unsigned int token2;                                        
  1415. unsigned int token3;                                        
  1416. void far*    *pointer1;            
  1417. void far*    *pointer2;                                    
  1418. void far*    *pointer3;                                    
  1419. {
  1420.    unsigned int tokens[3];      /* Set three array entries to pass */
  1421.                                 /* seteptrs()                      */
  1422.    void far*    pointers[3];    /* Set three array entries to be   */
  1423.                                 /* passed back from seteptrs()     */
  1424.    unsigned int status;         /* Status of EMM and MEMLIB        */
  1425.  
  1426.    tokens[0] = token1;
  1427.    tokens[1] = token2;
  1428.    tokens[2] = token3;
  1429.  
  1430.    /*********************************************************/
  1431.    /* Call seteptrs() to map in the blocks identified by    */
  1432.    /* token1, token2, and token3 and return their pointers. */
  1433.    /*********************************************************/
  1434.  
  1435.    status = seteptrs (3, tokens, pointers);
  1436.  
  1437.    if (status == PASSED)
  1438.    {
  1439.       *pointer1 = pointers[0];
  1440.       *pointer2 = pointers[1];
  1441.       *pointer3 = pointers[2];
  1442.    }
  1443.    return (status);
  1444.  
  1445. }  /** end set3eptrs **/
  1446.  
  1447. /*$PAGE*/
  1448. /**********************************************************************/
  1449. /*                                                                    */
  1450. /*     Name:  unsigned int push_context (void)                        */
  1451. /*                                                                    */
  1452. /*     Description:                                                   */
  1453. /*        Pushes the current mapping context onto an internal stack.  */
  1454. /*     The routine pop_context() can be used to restore the context   */
  1455. /*     saved by this routine.  Note that for each push we do we must  */
  1456. /*     do a pop.                                                      */
  1457. /*                                                                    */
  1458. /*     Parameters: None                                               */
  1459. /*                                                                    */
  1460. /*     Results returned:                                              */
  1461. /*        PASSED    Operation successful                              */
  1462. /*        error     Non-zero value, see "ERRORS.H" or EMS table A-2   */
  1463. /*                                                                    */
  1464. /*     Calling sequence:                                              */
  1465. /*     #include "memlib.h"                                            */
  1466. /*     #include "errors.h"                                            */
  1467. /*      ...                                                           */
  1468. /*     unsigned int status;                                           */
  1469. /*      ...                                                           */
  1470. /*     status = push_context();                                       */
  1471. /*     if (status == PASSED)                                          */
  1472. /*         { continue normal code }                                   */
  1473. /*     else                                                           */
  1474. /*         { error condition }                                        */
  1475. /*                                                                    */
  1476. /*     Calls: get_partial_context()                                   */
  1477. /*            init_exp_mem()                                          */
  1478. /*                                                                    */
  1479. /*     Called by: Application                                         */
  1480. /*                                                                    */
  1481. /*     Globals referenced/modified: context_ptrs                      */
  1482. /*                                  context_size                      */
  1483. /*                                  exp_initialized                   */
  1484. /*                                  partial_page_map                  */
  1485. /*                                  context_top                       */
  1486. /*                                                                    */
  1487. /**********************************************************************/
  1488.  
  1489. unsigned int push_context (void)
  1490. {
  1491.    unsigned int status;         /* The status of EMM and MELIB */
  1492.  
  1493.    /**************************/
  1494.    /* Assume this will pass. */
  1495.    /**************************/
  1496.  
  1497.    status = PASSED;
  1498.  
  1499.    /*************************************************************/
  1500.    /* Initialize expanded memory if we haven't already done so. */
  1501.    /*************************************************************/
  1502.  
  1503.    if (!exp_initialized)
  1504.       status = init_exp_mem();
  1505.  
  1506.    if (status == PASSED)
  1507.    {
  1508.       /**************************************/
  1509.       /* Increment our variable for keeping */ 
  1510.       /* track of top of our context stack. */
  1511.       /**************************************/
  1512.  
  1513.       context_top++;
  1514.  
  1515.       /***********************************************************/
  1516.       /* We have an array of pointers that keep track of the     */
  1517.       /* saved context.  Make sure we stay with our array limit. */
  1518.       /***********************************************************/
  1519.  
  1520.       if (context_top < MAX_CONTEXTS_AVAILABLE)
  1521.       {
  1522.          /***************************************************************/
  1523.          /* Allocate space in conventional memory to save this context. */
  1524.          /* Then call get_partial_page_map to do the actual save.       */
  1525.          /***************************************************************/
  1526.  
  1527.          context_ptrs[context_top] = (CONTEXT_STRUCT *) malloc (context_size);
  1528.  
  1529.          /*************************************************/
  1530.          /* Make sure we have enough conventional memory. */
  1531.          /*************************************************/
  1532.  
  1533.          if (context_ptrs[context_top] == NULL)
  1534.             status = MALLOC_FAILURE;
  1535.          else
  1536.             status = get_partial_context (&partial_page_map, 
  1537.                                           context_ptrs[context_top]);
  1538.       }
  1539.       else
  1540.          status = MAX_PUSH_CONTEXTS_EXCEEDED;
  1541.  
  1542.       /*************************************************/
  1543.       /* If status failed, reset top of context stack. */
  1544.       /*************************************************/
  1545.  
  1546.       if (status != PASSED)
  1547.          context_top--;
  1548.    }
  1549.  
  1550.    return (status);
  1551.  
  1552. } /** end push_context **/
  1553.  
  1554. /*$PAGE*/
  1555. /**********************************************************************/
  1556. /*                                                                    */
  1557. /*     Name:  unsigned int pop_context (void)                         */
  1558. /*                                                                    */
  1559. /*     Description:                                                   */
  1560. /*        Pops the last context saved by a call to push_context().    */
  1561. /*     Note that for each push we do we must do a pop.                */
  1562. /*                                                                    */
  1563. /*     Parameters: None                                               */
  1564. /*                                                                    */
  1565. /*     Results returned:                                              */
  1566. /*        PASSED    Operation successful                              */
  1567. /*        error     Non-zero value, see "ERRORS.H" or EMS table A-2   */
  1568. /*                                                                    */
  1569. /*     Calling sequence:                                              */
  1570. /*     #include "memlib.h"                                            */
  1571. /*     #include "errors.h"                                            */
  1572. /*      ...                                                           */
  1573. /*     unsigned int status;                                           */
  1574. /*      ...                                                           */
  1575. /*     status = pop_context();                                        */
  1576. /*     if (status == PASSED)                                          */
  1577. /*         { continue normal code }                                   */
  1578. /*     else                                                           */
  1579. /*         { error condition }                                        */
  1580. /*                                                                    */
  1581. /*     Calls: set_partial_context()                                   */
  1582. /*            init_exp_mem()                                          */
  1583. /*                                                                    */
  1584. /*     Called by: Application                                         */
  1585. /*                                                                    */
  1586. /*     Globals referenced/modified: context_ptrs                      */
  1587. /*                                  exp_initialized                   */
  1588. /*                                  context_top                       */
  1589. /*                                                                    */
  1590. /**********************************************************************/
  1591.  
  1592. unsigned int pop_context (void)
  1593. {
  1594.    unsigned int status;         /* The status of EMM and MEMLIB) */
  1595.  
  1596.    /**************************/
  1597.    /* Assume this will pass. */
  1598.    /**************************/
  1599.  
  1600.    status = PASSED;
  1601.  
  1602.    /*************************************************************/
  1603.    /* Initialize expanded memory if we haven't already done so. */
  1604.    /*************************************************************/
  1605.  
  1606.    if (!exp_initialized)
  1607.       status = init_exp_mem();
  1608.  
  1609.    if (status == PASSED)
  1610.    {
  1611.       /********************************************/
  1612.       /* Make sure there is a context to restore. */
  1613.       /********************************************/
  1614.  
  1615.       if (context_top != NO_CONTEXTS)
  1616.       {
  1617.          /*********************************************************/
  1618.          /* Save the context using set_partial_context(), storing */
  1619.          /* the information an our stack (context_ptrs array).    */
  1620.          /*********************************************************/
  1621.  
  1622.          status = set_partial_context (context_ptrs[context_top]);
  1623.          if (status == PASSED)
  1624.  
  1625.             /**************************************************************/
  1626.             /* Free the conventional memory we used to save this context. */
  1627.             /**************************************************************/
  1628.  
  1629.             free (context_ptrs[context_top]);
  1630.       }
  1631.       else
  1632.          status = NO_CONTEXT_AVAILABLE_TO_POP;
  1633.  
  1634.       /**********************************************/
  1635.       /* If status passed, decrement stack pointer. */
  1636.       /**********************************************/
  1637.  
  1638.       if (status == PASSED)
  1639.          if (context_top > 0)
  1640.             context_top--;
  1641.          else
  1642.             context_top = NO_CONTEXTS;
  1643.    }
  1644.  
  1645.    return (status);
  1646.  
  1647. } /** end pop_context **/
  1648.  
  1649. /*$PAGE*/  
  1650. /**********************************************************************/
  1651. /*                                                                    */
  1652. /*     Name:  unsigned int effreeall (void)                           */
  1653. /*                                                                    */
  1654. /*     Description:                                                   */
  1655. /*        Frees all handles, pages and blocks.  Prepare for program   */
  1656. /*     termination.                                                   */
  1657. /*                                                                    */
  1658. /*     Parameters: None                                               */
  1659. /*                                                                    */
  1660. /*     Results returned:                                              */
  1661. /*        PASSED    Operation successful                              */
  1662. /*        error     Non-zero value, see "ERRORS.H" or EMS table A-2   */
  1663. /*                                                                    */
  1664. /*     Calling sequence:                                              */
  1665. /*     #include "memlib.h"                                            */
  1666. /*     #include "errors.h"                                            */
  1667. /*                                                                    */
  1668. /*     unsigned int status;                                           */
  1669. /*      ...                                                           */
  1670. /*     status = effree();                                             */
  1671. /*     if (status == PASSED)                                          */
  1672. /*        { continue normal code }                                    */
  1673. /*     else                                                           */
  1674. /*        { error condition }                                         */
  1675. /*                                                                    */
  1676. /*     Calls: dealloc_pages()                                         */
  1677. /*            map_umap_page()                                         */
  1678. /*                                                                    */
  1679. /*     Called by: Application                                         */
  1680. /*                effree()                                            */
  1681. /*                                                                    */
  1682. /*     Globals referenced/modified: app_handle                        */
  1683. /*                                  exp_initialized                   */
  1684. /*                                  man_handle                        */
  1685. /*                                  num_pages_in_page_frame           */
  1686. /*                                  context_ptrs                      */
  1687. /*                                  context_top                       */
  1688. /*                                                                    */
  1689. /**********************************************************************/
  1690.  
  1691. unsigned int effreeall (void)
  1692. {
  1693.    unsigned int status;         /* The status of EMM and MEMLIB */
  1694.    unsigned int j;              /* Looping variable             */
  1695.  
  1696.    status = PASSED;
  1697.  
  1698.    /*****************************************************************/
  1699.    /*  If MEMLIB has not been initialized no need to free anything. */
  1700.    /*****************************************************************/
  1701.    
  1702.    if (exp_initialized)
  1703.    {
  1704.  
  1705.       /**************************************/
  1706.       /* Unmap all pages in the page frame. */
  1707.       /**************************************/
  1708.  
  1709.       for (j = 0; (status == PASSED) && 
  1710.                   (j < num_pages_in_page_frame); j++)
  1711.       {
  1712.          status = map_unmap_page(j, UNMAPPED, man_handle);
  1713.       }
  1714.  
  1715.       if (status == PASSED)
  1716.       {
  1717.          /***********************************************/
  1718.          /* Deallocate the pages and handle for MEMLIB. */
  1719.          /***********************************************/
  1720.  
  1721.          status = dealloc_pages (man_handle);
  1722.       }
  1723.       if (status == PASSED)
  1724.       {
  1725.          /********************************************************/
  1726.          /* Deallocate the pages and handle for the application. */
  1727.          /********************************************************/
  1728.  
  1729.          status = dealloc_pages (app_handle);
  1730.  
  1731.          /***********************************/
  1732.          /* Reset exp_initialized to FALSE. */
  1733.          /***********************************/
  1734.  
  1735.          if (status == PASSED)
  1736.          {
  1737.             exp_initialized = FALSE;
  1738.    
  1739.             /***********************************************/
  1740.             /* Free up all space taken by pushed contexts. */
  1741.             /***********************************************/
  1742.  
  1743.             if (context_top != NO_CONTEXTS)
  1744.             {
  1745.                for (j = 0; j < context_top; j++)
  1746.                {
  1747.                   if (context_ptrs[j] != NULL)
  1748.                      free (context_ptrs[j]);
  1749.                }
  1750.             }
  1751.          }
  1752.       }
  1753.    }
  1754.    return(status);
  1755.  
  1756. } /** end effreeall **/
  1757.  
  1758.  
  1759.  
  1760.